44. Python内置函数

什么是Python内置函数?

  • Python内置函数(Built-in Functions)无需导入任何模块即可使用
  • 它们构成了Python编程的基础工具箱
  • C语言实现,比纯Python代码快10-100倍

内置函数的设计哲学

  • 高层抽象:隐藏底层实现细节,提供简洁接口
  • 泛型设计:同一函数可应用于多种数据类型
  • 性能优化:C语言底层实现,执行效率极高
  • 一致性:遵循统一的命名和调用约定

内置函数的功能分类

类别 代表函数 金融应用场景
数学运算 abs(), round(), sum() 收益计算,四舍五入
序列操作 len(), max(), min(), sorted() 价格排序,极值查找
迭代器 map(), filter(), zip() 数据转换,批量处理
类型转换 int(), float(), str() 数据清洗,类型转换
输入输出 print(), input(), open() 数据读取,结果输出

⭐ 平台任务解答代码

Listing 1
# 注:该代码块包含未完成的填空代码,需要在平台上完成
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
#任务一
stock = ["中信证券","华泰证券","国泰君安","招商证券","中国银河","广发证券","中信建投","国信证券","中金公司","申万宏源"]
print(len(stock)) #计算列表中元素的个数
print(list(enumerate(stock,start=1))) #创建带有索引并且以列表方式分输出


#任务二
profit = [205.39,130.36,98.85,87.69,78.84,78.63,70.47,64.27,61.64,54.75]
stock = ["中信证券","华泰证券","国泰君安","招商证券","中国银河","广发证券","中信建投","国信证券","中金公司","申万宏源"]  # 定义列表stock
profit_total = sum(profit)  #计算10家证券公司的净利润总和
profit_average = profit_total/len(stock)  # 获取数据长度

print("2023年净利润排名前10位的证券公司净利润总和(亿元)",profit_total)  # 输出2023年净利润排名前10位的证券公司净利润总和(
print("2023年净利润排名前10位的证券公司净利润平均数(亿元)",round(profit_average,4))  # 输出2023年净利润排名前10位的证券公司净利润平均数

#任务三
return_Q1 = [-0.0588,-0.0067,-0.0698,0.0239,-0.0059,-0.0672,-0.0739,-0.0193,-0.1543,0.0046]
return_max = max(return_Q1) #找出最大涨幅
return_min = min(return_Q1) #找出最小涨幅
print("2024年1季度股价的最大涨幅",return_max)  # 输出2024年1季度股价的最大涨幅
print("2024年1季度股价的最小涨幅",return_min)  # 输出2024年1季度股价的最小涨幅

price = [18.73,13.61,13.47,13.71,11.76,13.05,21.68,8.11,32.03,4.40]  # 定义列表price
price_sorted = sorted(price) #将股价由小到大排序
print(price_sorted)  # 输出价格数据

#任务四
stock = ["中信证券","华泰证券","国泰君安","招商证券","中国银河","广发证券","中信建投","国信证券","中金公司","申万宏源"]
# 定义列表code
code = ["600030","601688","601211","600999","601881","000776","601066","002736","601995","000166"]
profit = [205.39,130.36,98.85,87.69,78.84,78.63,70.47,64.27,61.64,54.75]  # 定义列表profit
# 定义列表return_Q1
return_Q1 = [-0.0588,-0.0067,-0.0698,0.0239,-0.0059,-0.0672,-0.0739,-0.0193,-0.1543,0.0046]
price = [18.73,13.61,13.47,13.71,11.76,13.05,21.68,8.11,32.03,4.40]  # 定义列表price
print(list(zip(stock,code,profit,return_Q1,price))) #将多个列表中对应的元素打包为一个元组并以列表方式输出

#任务五
fund = 1e7 #H公司的投资资金额
price_huatai = 13.76 #华泰证券股票
N = 100  # 设置期数/数量为100
share = N*int(fund/(price_huatai*N))  # 将数据转换为整数

print("H公司购买华泰证券的股票数量",share)  # 输出H公司购买华泰证券的股票数量

len() — 获取序列长度

  • 语法len(序列)
  • 返回序列中元素的个数
  • 适用于字符串、列表、元组、字典等
  • 时间复杂度为 O(1),直接读取内部长度信息
numbers = [1, 2, 3, 4, 5]
print(f'长度: {len(numbers)}')
长度: 5

max()min() — 求极值

  • max() 返回序列中的最大值
  • min() 返回序列中的最小值
  • 可通过 key 参数指定比较依据
numbers = [1, 2, 3, 4, 5]
print(f'最大值: {max(numbers)}')
print(f'最小值: {min(numbers)}')
最大值: 5
最小值: 1

max() / min() 的高级用法:key参数

  • key 参数指定用于比较的函数
  • 常用于字典列表中按某个键排序
# 找出PE最高和价格最低的股票
portfolio = [
    {'name': '茅台', 'price': 1850, 'pe': 45},
    {'name': '五粮液', 'price': 220, 'pe': 32},
    {'name': '招商银行', 'price': 45, 'pe': 8}
]

highest_pe = max(portfolio, key=lambda x: x['pe'])
print(f'PE最高: {highest_pe["name"]}, PE={highest_pe["pe"]}')

lowest_price = min(portfolio, key=lambda x: x['price'])
print(f'价格最低: {lowest_price["name"]}, 价格={lowest_price["price"]}')
PE最高: 茅台, PE=45
价格最低: 招商银行, 价格=45

sum() — 计算序列和

  • 语法sum(可迭代对象, 初始值=0)
  • 从左到右对元素求和
  • 只支持数值类型
numbers = [1, 2, 3, 4, 5]
print(f'求和: {sum(numbers)}')
求和: 15

sorted() — 排序

  • 返回排序后的新列表,原序列不变
  • reverse=True 可实现降序排序
  • Python的排序是稳定的(相等元素保持原顺序)
numbers = [1, 2, 3, 4, 5]
print(f'降序排序: {sorted(numbers, reverse=True)}')
降序排序: [5, 4, 3, 2, 1]

abs()round() — 数值处理

  • abs(x):返回绝对值
  • round(x, n):四舍五入到 n 位小数
print(f'绝对值: {abs(-10)}')
print(f'四舍五入: {round(3.14159, 2)}')
绝对值: 10
四舍五入: 3.14

注意:Python 3 的银行家舍入

  • Python 3 使用银行家舍入(Round Half to Even)
  • 当恰好为 0.5 时,舍入到最近的偶数
  • 目的是减少统计偏差
print(round(2.5))  # 2(最近的偶数)
print(round(3.5))  # 4(最近的偶数)

# 传统四舍五入需要使用 decimal 模块
from decimal import Decimal, ROUND_HALF_UP
print(Decimal('2.5').quantize(Decimal('1'), rounding=ROUND_HALF_UP))  # 3
2
4
3

pow() — 幂运算

  • 语法pow(底数, 指数) 等价于 底数 ** 指数
  • 支持模运算:pow(x, y, mod) 等价于 (x ** y) % mod
print(f'2的3次方: {pow(2, 3)}')
print(f'2的10次方对1000取模: {pow(2, 10, 1000)}')
2的3次方: 8
2的10次方对1000取模: 24

金融应用:基础统计量计算

# 收益率序列
returns = [0.05, -0.02, 0.03, 0.07, -0.01]

# 平均收益率
avg_return = sum(returns) / len(returns)
print(f'平均收益率: {avg_return:.2%}')

# 最大收益和最大亏损
print(f'最大收益: {max(returns):.2%}')
print(f'最大亏损: {min(returns):.2%}')

# 极差(Range)
range_value = max(returns) - min(returns)
print(f'收益极差: {range_value:.2%}')
平均收益率: 2.40%
最大收益: 7.00%
最大亏损: -2.00%
收益极差: 9.00%

map() — 映射函数到每个元素

  • 语法map(函数, 可迭代对象)
  • 返回迭代器,需用 list() 转换
  • 常用于批量数据类型转换
# 将字符串价格列表转换为浮点数
prices = ['10.5', '20.3', '15.8']
prices_float = list(map(float, prices))
print(f'转换为浮点数: {prices_float}')
转换为浮点数: [10.5, 20.3, 15.8]

filter() — 过滤元素

  • 语法filter(函数, 可迭代对象)
  • 函数返回 True 时保留元素
  • 常配合 lambda 表达式使用
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(f'偶数: {evens}')
偶数: [2, 4, 6, 8, 10]

zip() — 配对多个序列

  • 将多个序列对应位置的元素组合成元组
  • 最短序列为准
  • 常用于构造字典或并行遍历
names = ['张三', '李四', '王五']
ages = [25, 30, 35]

pairs = list(zip(names, ages))
print(f'配对: {pairs}')

# 直接构造字典
name_age_dict = dict(zip(names, ages))
print(f'字典: {name_age_dict}')
配对: [('张三', 25), ('李四', 30), ('王五', 35)]
字典: {'张三': 25, '李四': 30, '王五': 35}

enumerate() — 带索引遍历

  • 语法enumerate(可迭代对象, start=0)
  • 返回 (索引, 元素) 的迭代器
  • start 参数设置起始索引
stocks = ['茅台', '五粮液', '招行']
for index, stock in enumerate(stocks, start=1):
    print(f'{index}. {stock}')
1. 茅台
2. 五粮液
3. 招行

map() / filter() 与列表推导式对比

  • 列表推导式通常更Pythonic、更易读
  • 功能上两者等价
numbers = [1, 2, 3, 4, 5]

# map + lambda
squared_map = list(map(lambda x: x**2, numbers))

# 列表推导式(推荐)
squared_comp = [x**2 for x in numbers]

print(f'map方式: {squared_map}')
print(f'推导式: {squared_comp}')
map方式: [1, 4, 9, 16, 25]
推导式: [1, 4, 9, 16, 25]

zip() 的解包操作

  • zip(*) 可实现反向解包
  • 将元组列表拆分为多个独立序列
# zip 配对
matrix = [(1, 'a'), (2, 'b'), (3, 'c')]

# zip(*) 解包
numbers, letters = zip(*matrix)
print(f'数字: {numbers}')
print(f'字母: {letters}')
数字: (1, 2, 3)
字母: ('a', 'b', 'c')

金融应用:数据清洗流水线

# 原始数据:字符串格式的价格和数量
raw_data = [
    ('10.5', '100'),
    ('20.3', '200'),
    ('15.8', '150')
]

# 使用 map() 进行数据转换
prices = list(map(lambda x: float(x[0]), raw_data))
quantities = list(map(lambda x: int(x[1]), raw_data))

# 计算每笔交易金额
amounts = list(map(lambda p, q: p * q, prices, quantities))
print(f'交易金额: {amounts}')

# 过滤出金额大于2000的交易
large_trades = list(filter(lambda x: x > 2000, amounts))
print(f'大额交易: {large_trades}')
交易金额: [1050.0, 4060.0, 2370.0]
大额交易: [4060.0, 2370.0]

金融应用:计算最大回撤

  • 最大回撤是从峰值到谷底的最大跌幅
  • 是评估投资策略风险的关键指标
returns = [0.05, -0.02, 0.03, 0.07, -0.01]

cum_return = 1.0   # 初始累计收益
max_drawdown = 0    # 最大回撤
peak = 1.0          # 历史峰值

for r in returns:
    cum_return *= (1 + r)          # 更新累计收益
    if cum_return > peak:
        peak = cum_return          # 更新历史峰值
    drawdown = (peak - cum_return) / peak  # 计算当前回撤
    max_drawdown = max(max_drawdown, drawdown)

print(f'最大回撤: {max_drawdown:.2%}')
最大回撤: 2.00%

金融应用:简化版夏普比率

  • 夏普比率衡量单位风险的超额收益
  • 公式:\(\text{Sharpe} = \frac{\bar{R} - R_f}{\sigma}\)
import math

returns = [0.05, -0.02, 0.03, 0.07, -0.01]
mean = sum(returns) / len(returns)

# 计算标准差
variance = sum((r - mean) ** 2 for r in returns) / len(returns)
std_dev = math.sqrt(variance)

# 假设无风险利率2%(年化),252个交易日
risk_free_rate = 0.02
sharpe_ratio = (mean * 252 - risk_free_rate) / (std_dev * math.sqrt(252))
print(f'年化夏普比率: {sharpe_ratio:.2f}')
年化夏普比率: 11.04

金融应用:正收益天数与分位数

returns = [0.05, -0.02, 0.03, 0.07, -0.01]

# 统计正收益天数
positive_count = len([r for r in returns if r > 0])
print(f'正收益次数: {positive_count}/{len(returns)}')

# 计算中位数
sorted_returns = sorted(returns)
n = len(sorted_returns)
if n % 2 == 0:
    median = (sorted_returns[n//2 - 1] + sorted_returns[n//2]) / 2
else:
    median = sorted_returns[n//2]
print(f'中位数收益率: {median:.2%}')
正收益次数: 3/5
中位数收益率: 3.00%

all()any() 函数

  • all()所有元素为 True 时返回 True
  • any()任一元素为 True 时返回 True
returns = [0.01, 0.02, 0.03, -0.01, 0.02]

print(f'所有收益为正: {all(r > 0 for r in returns)}')
print(f'存在负收益: {any(r < 0 for r in returns)}')

# 检查投资组合权重归一化
weights = [0.3, 0.4, 0.3]
print(f'权重之和为1: {abs(sum(weights) - 1.0) < 1e-10}')
所有收益为正: False
存在负收益: True
权重之和为1: True

最佳实践总结

  • 优先使用内置函数:C实现、性能好、代码简洁
  • 列表推导式 > map/filter:更Pythonic、更易读
  • 大规模计算用NumPy:比内置函数快10-100倍
  • 避免修改正在遍历的列表:使用推导式创建新列表

常见陷阱

# 陷阱:修改正在遍历的列表
lst = [1, 2, 3, 4, 5]
# ❌ 错误做法:for item in lst: lst.remove(item)
# ✅ 正确做法:创建新列表
lst_odd = [x for x in lst if x % 2 != 0]
print(f'过滤偶数后: {lst_odd}')

# 陷阱:可变默认参数
def foo(lst=None):
    if lst is None:
        lst = []
    lst.append(1)
    return lst

print(foo())  # [1]
print(foo())  # [1](每次调用都是新列表)
过滤偶数后: [1, 3, 5]
[1]
[1]